package beautiful.butterfly.server.httpserver.mvc.aop;

import beautiful.butterfly.server.httpserver.mvc.aop.interceptor.impl.LoginInterceptor;
import beautiful.butterfly.server.httpserver.mvc.core.Controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 拦截器构建类：查找注解构建拦截器Map
 */
public class InterceptorBuilder {

    private static final List<Interceptor> $list = new ArrayList<Interceptor>();
    static Interceptor loginInterceptor = new LoginInterceptor();
    private static Logger logger = LoggerFactory.getLogger(InterceptorBuilder.class);
    private Map<Class<Interceptor>, Interceptor> interceptorMap = new HashMap<Class<Interceptor>, Interceptor>();

    /**
     * 构建Action的拦截器
     */
    public List<Interceptor> buildActionInterceptors(
            Class<? extends Controller> controllerClass, List<Interceptor> controllerInterceptList,
            Method method, List<Interceptor> methodInterceptorList) {
        List<Interceptor> allList = new ArrayList<Interceptor>();


        List<Interceptor> _loginInterceptorList = new ArrayList<Interceptor>();// 第一个
        List<Interceptor> _controllerInterceptList = new ArrayList<Interceptor>();
        List<Interceptor> _methodInterceptorList = new ArrayList<Interceptor>();
        // 存放拦截器

        // 第一个-针对是否登录
        boolean isAllowNotLogin = method.isAnnotationPresent(AllowNotLogin.class);
        if (isAllowNotLogin) {
            // 则在loginInterceptor拦截器不进行添加
        } else {
            _loginInterceptorList.add(loginInterceptor);
        }

        // 第二个-针对添加控制器拦截器前判断是否添加基础拦截器
        // 判读之前的
        ClearLayer controllerClearType = getClearTypeOnTheController(controllerClass);
        if (controllerClearType != null) {// 控制器上面有loginInterceptor和基础拦截器
            _loginInterceptorList.clear();// 此处的场景,两种清除方式都代表是把loginInterceptor和基础拦截器清除
            if (controllerClearType == ClearLayer.Before) {// ClearLayer.All同时需要把控制器上面的拦截器进行清除
                _controllerInterceptList.addAll(controllerInterceptList);
            }

        } else {
            _controllerInterceptList.addAll(controllerInterceptList);
        }

        // 第三个
        // 判读之前的
        ClearLayer methodClearType = getClearTypeOnTheMethod(method);
        if (methodClearType != null) {
            _loginInterceptorList.clear();
            _controllerInterceptList.clear();// 此处的场景,两种清除方式都代表是把loginInterceptor和基础拦截器和控制器拦截器清除
            if (methodClearType == ClearLayer.Before) {
                _methodInterceptorList.addAll(methodInterceptorList);
            }
        } else {
            _methodInterceptorList.addAll(methodInterceptorList);
        }

        /**
         * 需要对这些拦截器判断是否元素为空
         */
        for (Interceptor interceptor : _loginInterceptorList) {
            if (interceptor != null) {
                allList.add(interceptor);
            }

        }
        for (Interceptor interceptor : _controllerInterceptList) {
            if (interceptor != null) {
                allList.add(interceptor);
            }

        }
        for (Interceptor interceptor : _methodInterceptorList) {
            if (interceptor != null) {
                allList.add(interceptor);
            }

        }

        return allList;
    }

    /**
     * 构建控制器上面的拦截器
     */
    public List<Interceptor> buildControllerInterceptors(
            Class<? extends Controller> controllerClass) {
        Before before = controllerClass.getAnnotation(Before.class);
        return before != null ? createInterceptors(before) : $list;
    }

    /**
     * 构建方法上面的拦截器
     */
    public List<Interceptor> buildMethodInterceptors(Method method) {
        Before before = method.getAnnotation(Before.class);
        return before != null ? createInterceptors(before) : $list;
    }

    /**
     * 创建拦截器:每个拦截器只实例化一次
     */
    private List<Interceptor> createInterceptors(Before beforeAnnotation) {
        //
        List<Interceptor> interceptorList = new ArrayList<Interceptor>();
        @SuppressWarnings("unchecked")
        // :Before(values={xx.class,yy.class})
                Class<Interceptor>[] interceptorClasses = (Class<Interceptor>[]) beforeAnnotation.value();
        if (interceptorClasses != null && interceptorClasses.length > 0) {
            int length = interceptorClasses.length;
            for (int i = 0; i < length; i++) {
                boolean isOk = interceptorMap.containsKey(interceptorClasses[i]);
                if (isOk) {// 不包含
                    // 只实例化一次
                    interceptorList.add(interceptorMap.get(interceptorClasses[i]));// 获取实例
                    continue;
                } else {
                    try {
                        Interceptor interceptor = interceptorClasses[i].newInstance();
                        // IOCManage.injectById(interceptorClasses[i],
                        // interceptor);
                        interceptorMap.put(interceptorClasses[i], interceptor);
                        interceptorList.add(interceptor);// 获取实例
                    } catch (Exception e) {
                        logger.error("拦截器实例化失败");
                        throw new RuntimeException(e);
                    }
                }

            }
        }
        return interceptorList;
    }

    /**
     * 得到标记在控制器上的ClearInterceptor的值
     */
    private ClearLayer getClearTypeOnTheController(Class<?> controllerClass) {
        ClearInterceptor clearInterceptor = controllerClass.getAnnotation(ClearInterceptor.class);
        return clearInterceptor != null ? clearInterceptor.value() : null;
    }

    /**
     * 得到标记在方法上的ClearInterceptor的值
     */
    private ClearLayer getClearTypeOnTheMethod(Method method) {
        ClearInterceptor clearInterceptor = method.getAnnotation(ClearInterceptor.class);
        return clearInterceptor != null ? clearInterceptor.value() : null;
    }

}
